<?php
declare(strict_types=1);

namespace App\Common\Modular\Data\Serve;

use App\Common\Modular\Data\Model\RegionModel;
use Core\Basics\BasicsServe;
use Hyperf\Database\Model\Builder;
use Zms\Unit\Arr;
use Core\HyperfUnit\Callback;
use Psr\SimpleCache\InvalidArgumentException;
use Zms\Unit\Is;

class RegionServe extends BasicsServe
{

    /**
     * @return RegionModel::class
     */
    public static function model(): string
    {
        return RegionModel::class;
    }


    /**
     * 名称搜索器
     * @param Builder $query
     * @param $keyword
     * @return void
     */
    public function searchName(Builder $query, $keyword): void
    {
        if (Is::notEmpty($keyword)) {
            if (is_string($keyword)) {
                $query->whereRaw("(`name` LIKE ? OR `shortname` LIKE ?)", ["%$keyword%", "%$keyword%"]);
            }
        }
    }


    /**
     * @param int $province_id
     * @param int $city_id
     * @param int $area_id
     * @return array
     */
    public function getInfo(int $province_id = 0, int $city_id = 0, int $area_id = 0): array
    {
        $key = "region_info_{$province_id}{$city_id}{$area_id}";
        try {
            if ($this->cache->has($key)) {
                return $this->cache->get($key);
            }
            $data = [];
            if ($province_id) {
                $province = $this->search(['level' => 1, 'id' => $province_id])->value('name');
                if ($province) {
                    $data[] = $province;
                } else {
                    $this->cache->set($key, []);
                    return [];
                }
            }

            if ($city_id) {
                $city = $this->search(['level' => 2, 'id' => $city_id])->value('name');
                if ($city) {
                    $data[] = $city;
                } else {
                    $this->cache->set($key, []);
                    return [];
                }
            }

            if ($area_id) {
                $area = $this->search(['level' => 3, 'id' => $area_id])->value('name');
                if ($area) {
                    $data[] = $area;
                } else {
                    $this->cache->set($key, []);
                    return [];
                }
            }

            $this->cache->set($key, $data);

            return $data;
        } catch (InvalidArgumentException) {
            return [];
        }
    }


    /**
     * 获取热门城市
     */
    public function getHotCity(array $find = ['id', 'name']): array
    {
        return $this->search(['is_hot' => 1, 'level' => 2])->select($find)->get()->toArray();
    }


    /**
     * 获取热门城市
     */
    public function getProvinceAll(array $find = ['id', 'name'], string $order = "id ASC"): array
    {
        return $this->search(['level' => 1])->select($find)->orderByRaw($order)->get()->toArray();
    }


    /**
     * 获取热门城市
     */
    public function getCityAll(array $find = ['id', 'name'], string $order = "id ASC"): array
    {
        return $this->search(['level' => 2])->select($find)->orderByRaw($order)->get()->toArray();
    }


    /**
     * 获取城市下的区域
     */
    public function getProvinceByCity(int $pid, array $find = ['id', 'name'], string $order = "id ASC"): array
    {
        return $this->search(['level' => 2, 'pid' => $pid])->select($find)->orderByRaw($order)->get()->toArray();
    }


    /**
     * 获取城市下的区域
     */
    public function getCityByArea(int $pid, array $find = ['id', 'name'], string $order = "id ASC"): array
    {
        return $this->search(['level' => 3, 'pid' => $pid])->select($find)->orderByRaw($order)->get()->toArray();
    }


    /**
     * 获取城市下的区域
     */
    public function getAreaSuperior(int $pid): array
    {
        $info = [0, 0, 0];
        if (!$pid) {
            return $info;
        }
        $area = $this->search(['level' => 3, 'id' => $pid])->select(['id', 'pid'])->first();
        if ($area) {
            $info[2] = $area['id'];
            $city = $this->search(['level' => 2, 'id' => $area['pid']])->select(['id', 'pid'])->first();
            if ($city) {
                $info[1] = $city['id'];
                $info[0] = $city['pid'];
            }
        }
        return $info;
    }

    /**
     * 获取省市地区树
     * @return array
     */
    public function getProvinceCityByTree(): array
    {
        return Callback::cache(__METHOD__, function () {
            $all = $this->search(['level' => [1, 2]])->orderByRaw('id ASC,pid ASC')->select(['id', 'name', 'pid'])->get()->toArray();
            foreach ($all as &$item) {
                $item['value'] = (string)$item['id'];
                $item['label'] = (string)$item['name'];
            }
            return Arr::getTree($all);
        });
    }

    /**
     * 获取地区树
     */
    public function getTreeFormData()
    {
        return Callback::cache(__METHOD__, function (): array {
            $all = $this->search()->orderByRaw('id ASC,pid ASC')->select(['id', 'name', 'pid'])->get()->toArray();
            foreach ($all as &$item) {
                $item['value'] = (string)$item['id'];
                $item['label'] = (string)$item['name'];
            }
            return Arr::getTree($all);
        }, 3600 * 24 * 30);
    }
}